﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using Conexion;
using System.IO;

namespace Manager
{
    class AdminController
    {

        private const string CMD_AGREGAR = "01";
        private const string CMD_QUITAR = "02";
        private const int CANT_MAX_SERV = 5;
        private Thread th = null;

        public AdminController()
        {
        }

        public void IniciarServicio()
        {
            Thread th = new Thread(AtenderAdmin);
            th.Start();
            
        }

        private void AtenderAdmin()
        {
            th = new Thread(EscucharAdmin);
            th.Start();
        }

        private void EscucharAdmin()
        {
            try
            {
                TcpListener listener = ListenerTCP.obtenerTcpListener(Manager.conf.Ip_administrador, Manager.conf.Puerto_administrador);
                listener.Start();

                TcpClient admin;
                Console.WriteLine("Escuchando peticiones del administrador en el puerto : " + Manager.conf.Puerto_administrador);

                while (true)
                {
                    admin = listener.AcceptTcpClient();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcesarPeticionAdmin), admin);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error al conectarse con el administrador: " + ex.Message);
            }
        }

        private void ProcesarPeticionAdmin(Object admin)
        {
            TcpClient tcpClient = (TcpClient)admin;
            NetworkStream ns;
            byte[] datos = new byte[1024];
            string hdr = "";
            string cmd = "";
            string response = "";
            string respuestaAEnviar = "RES";

            ns = tcpClient.GetStream();
            ns.Read(datos, 0, 3);
            hdr = Encoding.UTF8.GetString(datos).Substring(0, 3);

            if (hdr.Equals("REQ"))
            {
                ns.Read(datos, 0, 2);
                cmd = Encoding.UTF8.GetString(datos).Substring(0, 2);
                respuestaAEnviar += cmd;
                char[] cero = new char[] { '0' };
                switch (cmd)
                {
                    case CMD_AGREGAR:
                        ns.Read(datos, 0, 15);
                        string NOMBRE = Encoding.UTF8.GetString(datos).Substring(0, 15);
                        ns.Read(datos, 0, 15);
                        string IP = Encoding.UTF8.GetString(datos).Substring(0, 15);
                        ns.Read(datos, 0, 5);
                        string PUERTO = Encoding.UTF8.GetString(datos).Substring(0, 5);
                        if (Manager.conf.ObtenerCantServidores() < CANT_MAX_SERV)
                        {
                            ServerNode m = new ServerNode(IP.TrimStart(cero), int.Parse(PUERTO.TrimStart(cero)), NOMBRE.TrimStart(cero));
                            int id = m.Identificador;
                            Manager.conf.AgreagarServidor(m);
                            respuestaAEnviar += "0"; //exito
                        }
                        else
                        {
                            respuestaAEnviar += "1"; //error
                        }
                        break;
                    case CMD_QUITAR:
                        ns.Read(datos, 0, 15);
                        IP = Encoding.UTF8.GetString(datos).Substring(0, 15).TrimStart(cero);
                        ns.Read(datos, 0, 5);
                        PUERTO = Encoding.UTF8.GetString(datos).Substring(0, 5).TrimStart(cero);
                        ServerNode aux = null;
                        foreach (ServerNode m in Manager.conf.ObtenerServidores())
                        {
                            if ((m.Ip.Equals(IP)) && (m.Puerto == int.Parse(PUERTO)))
                                aux = m;
                        }
                        if (aux != null) {
                            Manager.conf.EliminarServidor(aux);
                            respuestaAEnviar += "0"; //exito
                        }
                        else
                        {
                            respuestaAEnviar += "1"; //error
                        }
                        break;
                    default:
                        Console.WriteLine("Error");
                        break;
                }
                byte[] respBy = Encoding.UTF8.GetBytes(respuestaAEnviar);
                ns.Write(respBy, 0, respBy.Length);
                ns.Flush();
            }
            else
            {
                //throw ex
            }
            byte[] datosRespuesta = Encoding.UTF8.GetBytes(response);
            StreamWriter str = new StreamWriter(tcpClient.GetStream());
            str.Write(response);
            str.Flush();
        }

    }
}
